// Package baselog
// @Title baselog[简述该包的主要作用]
// @Description
// @Author  cnHuaShao
// @since v0.0.1
// @Version v1.0.0
// @Date 2024/4/21 21:41
// @Update 2024/4/21 21:41
package baselog

import (
	"FinancialManagement/src/base/config"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"os"
	"time"
)

var (
	Logger      *zap.Logger
	SugarLogger *zap.SugaredLogger
)

// InitLogger 初始化Logger
func InitLogger() (err error) {
	// 初始一个日志文件对象，具备自动分割和清除逻辑
	infoWriteSyncer := getLogWriter(config.Get().Log.Filename)
	// 初始一个异常日志文件对象
	errWriteSyncer := getLogWriter(config.Get().Log.ErrFilename)
	// 初始一个日志配置对象
	encoder := getEncoder()
	// 设定日志级别
	var l = new(zapcore.Level)
	err = l.UnmarshalText([]byte(config.Get().Log.Level))
	if err != nil {
		return
	}

	// 自定义日志级别：自定义Info级别
	infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl < zapcore.WarnLevel && lvl >= *l
	})
	// 自定义日志级别：自定义Warn级别
	warnLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
		return lvl >= zapcore.WarnLevel && lvl >= *l
	})

	// 打印到控制台和日志文件
	core := zapcore.NewTee(
		// 将info及以下写入logPath，NewConsoleEncoder 是非结构化输出
		zapcore.NewCore(zapcore.NewConsoleEncoder(encoder), zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), infoWriteSyncer), infoLevel),
		// warn及以上写入errPath
		zapcore.NewCore(zapcore.NewConsoleEncoder(encoder), zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stderr), errWriteSyncer), warnLevel),
	)
	Logger = zap.New(core, zap.AddCaller())
	SugarLogger = Logger.Sugar()

	Logger.Info("zap logger 初始化完成")
	return
}

// getLogWriter
// @Description: 日志文件分割配置
// @param filename
// @return zapcore.WriteSyncer
func getLogWriter(fileName string) zapcore.WriteSyncer {
	lumberJackLogger := &lumberjack.Logger{
		Filename:   fileName,
		MaxSize:    config.Get().Log.MaxSize,    // 最大M数，超过则切割
		MaxBackups: config.Get().Log.MaxBackups, // 最大文件保留数，超过就删除最老的日志文件
		MaxAge:     config.Get().Log.MaxAge,     // 保存30天
		Compress:   config.Get().Log.Compress,   // 是否压缩
	}
	return zapcore.AddSync(lumberJackLogger)
}

// getEncoder
// @Description: 初始一个日志配置对象
// @return zapcore.Encoder
func getEncoder() zapcore.EncoderConfig {
	encoderConfig := zap.NewProductionEncoderConfig()
	// 输出的时间格式
	encoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
		enc.AppendString(t.Format("2006-01-02 15:04:05"))
	}
	// 时间输出时使用的标记名称
	encoderConfig.TimeKey = "time"
	// 将日志级别转换成大写（INFO，WARN，ERROR等）
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	// 编码持续时间，将 time.Duration 序列化为经过的浮点数秒数。
	encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder
	// 采用短文件路径编码输出
	encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
	return encoderConfig
}
